package com.bryantkobe.myspringcode.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.io.Serial;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @description: 业务异常基类
 * @author: alienwarezzl
 * @date: 2025/9/22
 */
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class BusinessException extends RuntimeException{

    @Serial
    private static final long serialVersionUID = 1L;

    //错误码（用于前端识别和国际化）
    private final String errorCode;

    // 错误参数（用于国际化消息模板填充）
    private final Map<String,Object> errorParams;

    // 时间戳（异常发生时间）
    private final long timestamp;

    // 线程信息（便于调试分布式系统）
    private final String threadInfo;

    public BusinessException(String errorCode,String message){
        this(errorCode,message,null,null);
    }

    public BusinessException(String errorCode,String message,
                             Throwable cause,Map<String,Object> errorParams) {
        super(message,cause);
        this.errorCode = errorCode;
        this.errorParams = errorParams != null ? new ConcurrentHashMap<>(errorParams) : new ConcurrentHashMap<>();
        this.timestamp = System.currentTimeMillis();
        this.threadInfo = Thread.currentThread().getName() +
                "(ID:" + Thread.currentThread().threadId() + ")";
    }

    public ExceptionDetail toDetail(){
        return new ExceptionDetail(
                this.errorCode,
                this.getMessage(),
                this.errorParams,
                this.timestamp,
                this.threadInfo,
                this.getStackTrace().length > 0 ?
                        this.getStackTrace()[0].toString() : "Unknown"
        );
    }

    /**
     * 添加上下文参数（使用JDK21的字符串模板）
     */
    public BusinessException withParam(String key, Object value) {
        this.errorParams.put(key, value);
        return this;
    }

    /**
     * 批量添加上下文参数
     */
    public BusinessException withParams(Map<String, Object> params) {
        if (params != null) {
            this.errorParams.putAll(params);
        }
        return this;
    }

    /**
     * 静态工厂方法 - 使用JDK21的字符串模板
     */
    public static BusinessException of(String errorCode, String template, Object... args) {
        String message = String.format(template, args);
        return new BusinessException(errorCode, message);
    }

    /**
     * 快速创建方法 - 结合枚举使用
     */
    public static BusinessException of(ExceptionEnum exceptionEnum) {
        return new BusinessException(
                exceptionEnum.getErrorCode(),
                exceptionEnum.getDefaultMessage()
        );
    }

    /**
     * 快速创建方法 - 带参数
     */
    public static BusinessException of(ExceptionEnum exceptionEnum, Object... params) {
        String message = String.format(exceptionEnum.getDefaultMessage(), params);
        return new BusinessException(exceptionEnum.getErrorCode(), message);
    }

    public String getErrorCode() {
        return errorCode;
    }

    public Map<String, Object> getErrorParams() {
        return new ConcurrentHashMap<>(errorParams);
    }

    public long getTimestamp() {
        return timestamp;
    }

    public String getThreadInfo() {
        return threadInfo;
    }

    /**
     * 重写toString方法，提供更友好的异常信息
     */
    @Override
    public String toString() {
        return String.format("BusinessException[code=%s, message=%s, thread=%s, time=%d]",
                errorCode, getMessage(), threadInfo, timestamp);
    }
}
